package com.my.code.pool;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

/**
 * 手动拆分任务
 */
public class ForJoinAcc implements Accumulation {

    private final ForkJoinPool pool;

    public ForJoinAcc() {
        //也可以使用公共线程池 ForkJoinPool.commonPool();
        this.pool = new ForkJoinPool();
    }

    //执行任务RecursiveTask：有返回值  RecursiveAction：无返回值
    private static class Task extends RecursiveTask<Long> {

        private final long[] numbs;
        private final int from;
        private final int to;

        public Task(long[] numbs, int from, int to) {
            this.numbs = numbs;
            this.from = from;
            this.to = to;
        }

        //此方法为ForkJoin的核心方法：对任务进行拆分  拆分的好坏决定了效率的高低
        @Override
        protected Long compute() {
            if (to - from <= 10000) {
                long total = 0;
                for (int i = from; i <= to; i++) {
                    total += numbs[i];
                }
                return total;
            } else {// 否则，把任务一分为二，递归拆分(注意此处有递归)到底拆分成多少分 需要根据具体情况而定
                int middle = (from + to) / 2;
                Task leftTask = new Task(numbs, from, middle);
                Task rightTask = new Task(numbs, middle + 1, to);
                leftTask.fork();
                rightTask.fork();
                return leftTask.join() + rightTask.join();
            }
        }
    }

    @Override
    public long acc(long[] numbs) {
        Long result = pool.invoke(new Task(numbs, 0, numbs.length - 1));
        pool.shutdown();
        return result;
    }
}
